#!/bin/bash

# K8s离线安装包下载脚本
# 用于在联网环境下载所有必要的K8s组件和依赖

set -e

# 配置变量
K8S_VERSION="1.28.4"
CONTAINERD_VERSION="1.7.8"
RUNC_VERSION="1.1.9"
CNI_VERSION="1.3.0"
CRICTL_VERSION="1.28.0"
HELM_VERSION="3.13.0"

# 创建下载目录
DOWNLOAD_DIR="./k8s-offline-packages"
mkdir -p ${DOWNLOAD_DIR}/{binaries,images,packages,scripts}

echo "=========================================="
echo "开始下载K8s离线安装包"
echo "K8s版本: ${K8S_VERSION}"
echo "下载目录: ${DOWNLOAD_DIR}"
echo "=========================================="

# 下载K8s二进制文件
echo "正在下载K8s二进制文件..."
K8S_BINARIES=(
    "kubeadm"
    "kubelet" 
    "kubectl"
)

for binary in "${K8S_BINARIES[@]}"; do
    echo "下载 ${binary}..."
    curl -L "https://dl.k8s.io/release/v${K8S_VERSION}/bin/linux/amd64/${binary}" \
        -o "${DOWNLOAD_DIR}/binaries/${binary}"
    chmod +x "${DOWNLOAD_DIR}/binaries/${binary}"
done

# 下载containerd
echo "正在下载containerd..."
curl -L "https://github.com/containerd/containerd/releases/download/v${CONTAINERD_VERSION}/containerd-${CONTAINERD_VERSION}-linux-amd64.tar.gz" \
    -o "${DOWNLOAD_DIR}/packages/containerd-${CONTAINERD_VERSION}-linux-amd64.tar.gz"

# 下载runc
echo "正在下载runc..."
curl -L "https://github.com/opencontainers/runc/releases/download/v${RUNC_VERSION}/runc.amd64" \
    -o "${DOWNLOAD_DIR}/binaries/runc"
chmod +x "${DOWNLOAD_DIR}/binaries/runc"

# 下载CNI插件
echo "正在下载CNI插件..."
curl -L "https://github.com/containernetworking/plugins/releases/download/v${CNI_VERSION}/cni-plugins-linux-amd64-v${CNI_VERSION}.tgz" \
    -o "${DOWNLOAD_DIR}/packages/cni-plugins-linux-amd64-v${CNI_VERSION}.tgz"

# 下载crictl
echo "正在下载crictl..."
curl -L "https://github.com/kubernetes-sigs/cri-tools/releases/download/v${CRICTL_VERSION}/crictl-v${CRICTL_VERSION}-linux-amd64.tar.gz" \
    -o "${DOWNLOAD_DIR}/packages/crictl-v${CRICTL_VERSION}-linux-amd64.tar.gz"

# 下载Helm
echo "正在下载Helm..."
curl -L "https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz" \
    -o "${DOWNLOAD_DIR}/packages/helm-v${HELM_VERSION}-linux-amd64.tar.gz"

# 下载K8s镜像列表
echo "正在生成K8s镜像列表..."
cat > ${DOWNLOAD_DIR}/scripts/k8s-images.txt << EOF
k8s.gcr.io/kube-apiserver:v${K8S_VERSION}
k8s.gcr.io/kube-controller-manager:v${K8S_VERSION}
k8s.gcr.io/kube-scheduler:v${K8S_VERSION}
k8s.gcr.io/kube-proxy:v${K8S_VERSION}
k8s.gcr.io/pause:3.9
k8s.gcr.io/etcd:3.5.9-0
k8s.gcr.io/coredns/coredns:v1.10.1
EOF

# 下载Docker镜像
echo "正在下载K8s Docker镜像..."
while IFS= read -r image; do
    echo "拉取镜像: $image"
    docker pull "$image"
    docker save "$image" > "${DOWNLOAD_DIR}/images/$(echo $image | tr '/' '_' | tr ':' '_').tar"
done < ${DOWNLOAD_DIR}/scripts/k8s-images.txt

# 下载系统依赖包（针对Ubuntu Server）
echo "正在下载系统依赖包..."
apt-get update
apt-get download kubelet kubeadm kubectl
mv *.deb ${DOWNLOAD_DIR}/packages/deb/

# 创建安装脚本
echo "正在创建安装脚本..."
cat > ${DOWNLOAD_DIR}/install_k8s.sh << 'EOF'
#!/bin/bash

# K8s离线安装脚本
# 在离线服务器上运行此脚本

set -e

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a /var/log/k8s-install.log
}

error() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" | tee -a /var/log/k8s-install.log
    exit 1
}

# 检查是否为root用户
if [ "$EUID" -ne 0 ]; then
    error "请使用root用户运行此脚本"
fi

log "开始K8s离线安装..."

# 安装系统依赖
log "安装系统依赖包..."
if [ -d "packages/deb" ]; then
    dpkg -i packages/deb/*.deb
    apt-get install -f  # 修复依赖关系
else
    log "警告: 未找到DEB包，请确保已安装kubelet, kubeadm, kubectl"
fi

# 安装containerd
log "安装containerd..."
tar -xzf packages/containerd-*.tar.gz -C /usr/local/
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml

# 安装runc
log "安装runc..."
cp binaries/runc /usr/local/bin/
chmod +x /usr/local/bin/runc

# 安装CNI插件
log "安装CNI插件..."
mkdir -p /opt/cni/bin
tar -xzf packages/cni-plugins-*.tgz -C /opt/cni/bin/

# 安装crictl
log "安装crictl..."
tar -xzf packages/crictl-*.tar.gz -C /usr/local/bin/
chmod +x /usr/local/bin/crictl

# 安装Helm
log "安装Helm..."
tar -xzf packages/helm-*.tar.gz
mv linux-amd64/helm /usr/local/bin/
chmod +x /usr/local/bin/helm

# 加载Docker镜像
log "加载Docker镜像..."
for image in images/*.tar; do
    log "加载镜像: $image"
    docker load < "$image"
done

# 启动containerd服务
log "启动containerd服务..."
systemctl daemon-reload
systemctl enable containerd
systemctl start containerd

# 配置kubelet
log "配置kubelet..."
systemctl enable kubelet

log "K8s离线安装完成！"
log "请运行 'kubeadm init' 初始化集群"
EOF

chmod +x ${DOWNLOAD_DIR}/install_k8s.sh

# 创建检查脚本
cat > ${DOWNLOAD_DIR}/check_k8s.sh << 'EOF'
#!/bin/bash

# K8s安装状态检查脚本

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

check_command() {
    if command -v $1 &> /dev/null; then
        log "✓ $1 已安装: $(which $1)"
        $1 --version 2>/dev/null || $1 version 2>/dev/null || log "  $1 版本信息获取失败"
    else
        log "✗ $1 未安装"
        return 1
    fi
}

check_service() {
    if systemctl is-active --quiet $1; then
        log "✓ $1 服务正在运行"
    else
        log "✗ $1 服务未运行"
        return 1
    fi
}

log "开始检查K8s安装状态..."

# 检查二进制文件
log "检查二进制文件..."
check_command kubectl
check_command kubeadm
check_command kubelet
check_command containerd
check_command crictl
check_command helm

# 检查服务状态
log "检查服务状态..."
check_service containerd
check_service kubelet

# 检查镜像
log "检查Docker镜像..."
docker images | grep -E "(k8s\.gcr\.io|pause|etcd|coredns)" || log "警告: 未找到K8s相关镜像"

# 检查网络插件
log "检查CNI插件..."
if [ -d "/opt/cni/bin" ] && [ "$(ls /opt/cni/bin | wc -l)" -gt 0 ]; then
    log "✓ CNI插件已安装"
    ls -la /opt/cni/bin/
else
    log "✗ CNI插件未安装"
fi

log "检查完成！"
EOF

chmod +x ${DOWNLOAD_DIR}/check_k8s.sh

# 创建部署说明
cat > ${DOWNLOAD_DIR}/README.md << 'EOF'
# K8s离线安装包

## 文件结构
```
k8s-offline-packages/
├── binaries/          # 二进制文件
├── images/           # Docker镜像
├── packages/         # 安装包
│   └── deb/          # Ubuntu DEB包
├── scripts/          # 脚本文件
├── install_k8s.sh    # 安装脚本
└── check_k8s.sh      # 检查脚本
```

## 部署步骤

### 1. 在联网环境运行下载脚本
```bash
chmod +x download_k8s.sh
./download_k8s.sh
```

### 2. 将整个k8s-offline-packages目录传输到离线服务器
```bash
# 使用scp传输
scp -r k8s-offline-packages root@server-ip:/root/

# 或使用rsync
rsync -avz k8s-offline-packages/ root@server-ip:/root/k8s-offline-packages/
```

### 3. 在离线服务器上安装
```bash
cd k8s-offline-packages
chmod +x install_k8s.sh
./install_k8s.sh
```

### 4. 检查安装状态
```bash
./check_k8s.sh
```

### 5. 初始化集群（仅在master节点）
```bash
kubeadm init --pod-network-cidr=10.244.0.0/16
```

### 6. 配置kubectl
```bash
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
```

### 7. 安装网络插件（如Flannel）
```bash
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
```

## 注意事项
- 确保所有服务器时间同步
- 关闭防火墙或配置相应规则
- 禁用swap分区
- 确保主机名唯一且符合DNS规范
EOF

echo "=========================================="
echo "下载完成！"
echo "下载目录: ${DOWNLOAD_DIR}"
echo "文件大小: $(du -sh ${DOWNLOAD_DIR})"
echo "=========================================="
echo ""
echo "下一步："
echo "1. 将 ${DOWNLOAD_DIR} 目录传输到离线服务器"
echo "2. 在服务器上运行 install_k8s.sh"
echo "3. 运行 check_k8s.sh 检查安装状态"
